package soap.entity.bo;

import com.alibaba.fastjson.JSONArray;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import soap.entity.exportbean.BasicTaskPlus;
import soap.entity.po.ExportRecord;
import soap.entity.po.Person;
import soap.feign.dto.PersonDto;
import soap.feign.service.MSUserServiceFeign;
import soap.service.ExportRecordService;
import soap.utils.ExportExcelTools;

import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static com.google.common.collect.Lists.partition;

/**
 * Created by ZhangPY on 2020/6/7
 * Belong Organization OVERUN-9299
 * overun9299@163.com
 * Explain:
 */
@Slf4j(topic = "Person-Export")
public class PersonBo extends BasicTaskPlus {


    private MSUserServiceFeign MSUserServiceFeign;

    private PersonDto personDto;

    private ExportRecordService exportRecordService;

    private String exportRecordId;

    private String filePath;


    public PersonBo(MSUserServiceFeign MSUserServiceFeign, PersonDto personDto, ExportRecordService exportRecordService, String exportRecordId, String filePath) {
        this.MSUserServiceFeign = MSUserServiceFeign;
        this.personDto = personDto;
        this.exportRecordService = exportRecordService;
        this.exportRecordId = exportRecordId;
        this.filePath = filePath;
    }

    @Override
    public void run() {
        Long startTime = System.currentTimeMillis();
        try {
            /** 定义线程数 **/
            int nThreads = 4;
            /** 生成文件 **/
            String personListForExport = MSUserServiceFeign.getPersonListForExport(personDto);

            if (StringUtils.isNotBlank(personListForExport)) {

                List<Person> people = JSONArray.parseArray(personListForExport, Person.class);
                Long startTime2 = System.currentTimeMillis();
                List<List<Person>> partition = partition(people, 60000);
                Long startTime3 = System.currentTimeMillis();
                int listIndex = 1;
                ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
                for (List<Person> list : partition) {
                    int listIndex2 = listIndex++;
                    executorService.execute(()->{
                        try {
                            String excelFileName = "Person-record-" + listIndex2 + "-" + + System.currentTimeMillis() + ".xlsx";
                            log.info("准备生成文件,文件路径" + filePath + excelFileName);
                            FileOutputStream fo = new FileOutputStream(filePath + excelFileName);
                            new ExportExcelTools(fo).writeHead(Person.class).writeList(list).exportData();
                            fo.flush();
                            fo.close();

                            /** 更新导出记录 */
                            ExportRecord exportRecord = new ExportRecord();
                            exportRecord.setId(exportRecordId);
                            exportRecord.setCompletionDate(LocalDateTime.now());
                            exportRecord.setState(1);
                            exportRecord.setFilePath(excelFileName);
                            exportRecordService.updateExportRecord(exportRecord);
                        } catch (Exception e) {
                            e.printStackTrace();
                            log.error(e.getMessage());
                        }
                    });

                }
                /** 不在接收新的任务 **/
                executorService.shutdown();
                /** 等待所有线程执行完毕 **/
                executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);

                Long endTime = System.currentTimeMillis();
                log.info("人员导出共 {} 条数据 , 采用{}线程 , 查询耗时 {} ms , 分解耗时 {} ms , 导出耗时 {} ms" , people.size(), nThreads, startTime2-startTime, startTime3-startTime2, endTime-startTime3);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
